//
//  VideoAndAudioDecoder.m
//  AppControllerDevices
//
//  Created by joker on 15/8/7.
//  Copyright (c) 2015年 joker. All rights reserved.
//

#import "VideoAndAudioDecoder.h"

@implementation VideoAndAudioDecoder

-(id)initVideoDecoder{
    if(self = [super init])
    {
            //注册所有可以处理的音视频格式
        av_register_all();
        
            //初始化帧指针
        self.pFrame = NULL;
        
            //寻找可以编解码指定格式的解码器
        self.pCodec = avcodec_find_decoder(CODEC_ID_H264);
        
        if (!self.pCodec)
        {
            NSLog(@"decoder not found!");
            return nil;
        }
        
            //分配编解码相关信息的内存
        self.pCodecCtx = avcodec_alloc_context3(self.pCodec);

        if(avcodec_open2(self.pCodecCtx, self.pCodec,NULL) >= 0){
            self.pFrame = av_frame_alloc();
            self.pFrameRGB = av_frame_alloc();
            
            if(self.pFrameRGB == NULL || self.pFrame == NULL)
            {
                NSLog(@"分配帧失败");
                return nil;
            }
            
            return self;
        }
        else {
            NSLog(@"avcodec_open2 failed!");
            return nil;
        }

    }
    return self;
}

-(void)VideoDecodeWithBuf:(char *)buf BufSize:(int)size{
    
    _VideoPacket.data = (uint8_t *)buf;
    _VideoPacket.size = size;
    
    
    int ret = avcodec_decode_video2(self.pCodecCtx, self.pFrame, &(_frameFinished), &_VideoPacket);
    
    if(ret <= 0 ){
        NSLog(@"decode frame failed!");
        return;
    }
    
    self.numBytes = avpicture_get_size(PIX_FMT_RGB24, self.pCodecCtx->width, self.pCodecCtx->height);
    
    self.buffer = av_malloc(self.numBytes);
    
    avpicture_fill((AVPicture *)self.pFrameRGB, self.buffer, PIX_FMT_RGB24, self.pCodecCtx->width, self.pCodecCtx->height);
    
    struct SwsContext * img_convert_ctx = NULL;
    img_convert_ctx = sws_getCachedContext(img_convert_ctx, self.pCodecCtx->width, self.pCodecCtx->height, self.pCodecCtx->pix_fmt, self.pCodecCtx->width, self.pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
    
    if(!img_convert_ctx)
    {
        NSLog(@"不能初始化 sws conversion context");
        return;
    }
    sws_scale(img_convert_ctx, (const uint8_t* const *)self.pFrame->data, self.pFrame->linesize, 0, self.pCodecCtx->height, self.pFrameRGB->data, self.pFrameRGB->linesize);
}

-(void)VideoDecoderDealloc{
    av_free_packet(&_VideoPacket);
    av_free(self.buffer);
    av_free(self.pFrameRGB);
    av_free(self.pFrame);
    avcodec_close(self.pCodecCtx);
}

-(id)initAudioDecoderWithFormat:(int)audioFormat ChannelIndex:(int) avIndex {
    if(self = [super init])
    {        
        self.audioOutFormat = audioFormat;
        self.channleIndex = avIndex;
        
        self.synlock = [[NSLock alloc] init];
        
            ///设置音频参数
        switch (self.audioOutFormat) {
            case MEDIA_CODEC_AUDIO_PCM:
                audioDescription.mFormatID = kAudioFormatLinearPCM;
                audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
                audioDescription.mSampleRate = 8000; //采样率
                
                audioDescription.mChannelsPerFrame = 1;///单声道
                audioDescription.mBitsPerChannel = 16;//每个采样点16bit量化
                
                audioDescription.mFramesPerPacket = 1;//每一个packet一侦数据
                audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) * audioDescription.mChannelsPerFrame;
                audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame*audioDescription.mFramesPerPacket ;
                break;
            case MEDIA_CODEC_AUDIO_G711A:
                audioDescription.mFormatID = kAudioFormatALaw;
                audioDescription.mSampleRate = 8000; //采样率
//                audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
                audioDescription.mChannelsPerFrame = 1;///单声道
                audioDescription.mFramesPerPacket = 1;//每一个packet一侦数据
                
//                audioDescription.mBitsPerChannel = 16;//每个采样点16bit量化
//                audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) * audioDescription.mChannelsPerFrame;
//                audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame*audioDescription.mFramesPerPacket ;
                break;
            case MEDIA_CODEC_AUDIO_AAC:
                audioDescription.mFormatID = kAudioFormatMPEG4AAC;
                audioDescription.mSampleRate = 8000; //采样率
                audioDescription.mChannelsPerFrame = 1;///单声道
                audioDescription.mFramesPerPacket = 1;//每一个packet一侦数据

//                audioDescription.mBitsPerChannel = 16;//每个采样点16bit量化
//                audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) * audioDescription.mChannelsPerFrame;
//                audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame*audioDescription.mFramesPerPacket ;
//                audioDescription.mBytesPerPacket= 6;
                break;
            default:
                NSLog(@"未知音频格式");
                break;
        }
        
            //创建一个从队列到硬件的输出
       AudioQueueNewOutput(&audioDescription, AudioPlayerAQInputCallback,(__bridge void *)(self), nil, nil, 0, &_audioQueue);//使用player的内部线程播
        
            //分配缓冲区
        for(int i=0;i<QUEUE_BUFFER_SIZE;i++)
        {
            int result =  AudioQueueAllocateBuffer(self.audioQueue, AUDIO_BUF_SIZE, &audioQueueBuffers[i]);
            NSLog(@"AudioQueueAllocateBuffer i = %d,result = %d",i,result);
        }
            //分配完缓冲区后，开始播放音频流
        AudioQueueStart(self.audioQueue, NULL);
    }
    return self;
}

-(void)AudioDecoderDealloc{
    AudioQueueDispose(self.audioQueue, true);
}

-(void)ReadPCMAndPlay:(char *)buf BufSize:(int)size BufIndex:(int)index {
        //加一步解码
    [self readPCMAndPlay:self.audioQueue buffer:audioQueueBuffers[index] WithDataBuf:buf AndSize:size];
}

    //音频播放辅助函数
-(void)readPCMAndPlay:(AudioQueueRef)outQ buffer:(AudioQueueBufferRef)outQB WithDataBuf:(char*)buf AndSize:(int)size
{
    [self.synlock lock];

    outQB->mAudioDataByteSize = size;
    Byte *audiodata = (Byte *)outQB->mAudioData;
    for(int i=0;i<size;i++)
    {
        audiodata[i] = buf[i];
    }
    /*
     将创建的buffer区添加到audioqueue里播放
     AudioQueueBufferRef用来缓存待播放的数据区，AudioQueueBufferRef有两个比较重要的参数，AudioQueueBufferRef->mAudioDataByteSize用来指示数据区大小，AudioQueueBufferRef->mAudioData用来保存数据区
     */
    AudioQueueEnqueueBuffer(outQ, outQB, 0, NULL);
    
    [self.synlock unlock];
}
-(void)checkUsedQueueBuffer:(AudioQueueBufferRef) qbuf
{
    if(qbuf == audioQueueBuffers[0])
    {
        NSLog(@"AudioPlayerAQInputCallback,bufferindex = 0");
    }
    if(qbuf == audioQueueBuffers[1])
    {
        NSLog(@"AudioPlayerAQInputCallback,bufferindex = 1");
    }
    if(qbuf == audioQueueBuffers[2])
    {
        NSLog(@"AudioPlayerAQInputCallback,bufferindex = 2");
    }
}
static void AudioPlayerAQInputCallback(void *input, AudioQueueRef outQ, AudioQueueBufferRef outQB)
{
    VideoAndAudioDecoder * decoder = (__bridge VideoAndAudioDecoder *)input;

    char buf[AUDIO_BUF_SIZE];
    unsigned int frameNo;
    int ret;
    FRAMEINFO_t frameInfo;
    
    while(true)
    {
        ret = avCheckAudioBuf(decoder.channleIndex);
        if (ret < 0) return;
        if (ret < 3) // determined by audio frame rate
        {
            usleep(120000);
            continue;
        }
        
        ret = avRecvAudioData(decoder.channleIndex, buf, AUDIO_BUF_SIZE, (char *)&frameInfo, sizeof(FRAMEINFO_t), &frameNo);
        
        if(ret == AV_ER_SESSION_CLOSE_BY_REMOTE)
        {
            NSLog(@"[AudioThreadWithDecoder] AV_ER_SESSION_CLOSE_BY_REMOTE");
            return;
        }
        else if(ret == AV_ER_REMOTE_TIMEOUT_DISCONNECT)
        {
            NSLog(@"[AudioThreadWithDecoder] AV_ER_REMOTE_TIMEOUT_DISCONNECT");
            return;
        }
        else if(ret == IOTC_ER_INVALID_SID)
        {
            NSLog(@"[AudioThreadWithDecoder] Session cant be used anymore");
            return;
        }
        else if (ret == AV_ER_LOSED_THIS_FRAME)
        {
            continue;
        }
            //进行音频解码并播放
        [decoder checkUsedQueueBuffer:outQB];
        if(ret >=0){
            NSLog(@"AAC Data Packet Size is %d",ret);
            [decoder readPCMAndPlay:outQ buffer:outQB WithDataBuf:buf+PADDINGBITS  AndSize:ret-PADDINGBITS];
            NSLog(@"AudioPlayerAQInputCallback - load more audio data");
            break;
        }
        else{
            NSLog(@"没有音频数据");
        }
    }
}
@end